from Tkinter import *
from elementtree.ElementTree import parse
import os
import tkFileDialog
import ProjectWidget
import FileHandler
'''
Created on Feb 27, 2011

@author: Armon
'''

class ProjectWizard():
    
    '''Pointer (number) corresponding to the window currently in use
    Python allows only for initialization of class member variables to some number'''
    currentWindowPointer = 0
    
    '''The maximum number of windows for the project wizard'''
    maxNoOfWindows = 0
    
    '''List of all windows for the wizard from the XML file
    Referencing a window is therefore as simple as windows[windowNumber]'''
    windows = []
    
    cachedWindows = []
    
    '''number for each respective window'''
    projectSettingsWindow=0
    importDocumentWindow=1
    corpusWindow=2
    corpusReviewWindow=3
    
    def __init__(self, mainFrame, masterFrame,frameController):
        '''
        Constructor
        '''
        
        '''Construct initial window to project wizard. It will be called with TopLevel(master)
        Place Next, Back, and Cancel buttons on the project window'''
        self.mainFrame = mainFrame
        self.masterFrame = masterFrame
        self.controller = frameController
        self.window = Toplevel(masterFrame)
        self.window.title("New Project Wizard")
        self.backButton = Button(self.window, text="Back", command = self.moveToPreviousWindow)
        self.backButton.grid(row = "15", column = "1")
        self.nextButton = Button(self.window, text="Next", command = self.moveToNextWindow)
        self.nextButton.grid(row = "15", column = "2")
        self.cancelButton = Button(self.window, text="Cancel", command = self.destroyWindow)
        self.cancelButton.grid(row= "15", column = "3")
        
        
    def run(self, startWindowNo):
        
        self.currentWindowPointer = startWindowNo    
        projectWizardStyleFile = parse('ProjectWizardStyle/NewProjectWizard.xml')
        self.maxNoOfWindows = len(projectWizardStyleFile.findall('window'))
        self.cachedWindows = [self.maxNoOfWindows]
        
        self.windows = projectWizardStyleFile.getiterator('window')
        
        '''Display the current window'''
        self.displayWindow()
        
    def moveToNextWindow(self):  
        #if we are on the project settings window, store data in memory in order
        #to be save to XML later
        if self.currentWindowPointer == self.importDocumentWindow:
            self.existingDocumentFilename = self.cachedWindows[self.importDocumentWindow][self.iterateCachedWindow('txtExistingDocumentFilename')].getWidget().get()
        elif self.currentWindowPointer == self.projectSettingsWindow:
            self.userName = self.cachedWindows[self.projectSettingsWindow][self.iterateCachedWindow('userName')].getWidget().get()
            self.projectTitle = self.cachedWindows[self.projectSettingsWindow][self.iterateCachedWindow('projectTitle')].getWidget().get()
        elif self.currentWindowPointer == self.corpusWindow:
            self.corpusPath = self.cachedWindows[self.corpusWindow][self.iterateCachedWindow("txtCorpusPath")].getWidget().get()  
        self.destroyWidgets()
        self.currentWindowPointer = self.currentWindowPointer + 1
        self.displayWindow()
    
    def moveToPreviousWindow(self):
        
        if self.currentWindowPointer > 0:
            self.destroyWidgets()
            self.currentWindowPointer = self.currentWindowPointer - 1
            '''displayPreviousWindow()'''
            self.displayWindow()
    
    def destroyWindow(self):
        
        del self.cachedWindows[:]
        self.window.destroy()
        
    def destroyWidgets(self):
        
        for i in range(len(self.cachedWindows[self.currentWindowPointer])):
            '''Determine if the window is to be destroyed'''
            widgetDestroy = self.cachedWindows[self.currentWindowPointer][i]
            
            if str(widgetDestroy.getDestroy()) != "false":
                widgetDestroy.getWidget().destroy()
        
        '''
        for i in range(len(self.currentWindow[self.currentWindowPointer])):
            self.currentWindow[self.currentWindowPointer][i].destroy()
        '''
            
    def previousValue(self, name, windowNumber):
            
        '''Get the window number of the widget'''
        '''tempWindowNumber = int(projectWidget.getWindowNumber())'''
        
        '''Find the widget in the cachedWindow list. Meaning iterate through all the windows and find the name'''
        
        for i in range(len(self.cachedWindows[windowNumber])):
            tempProjectWidget = self.cachedWindows[windowNumber][i]
            
            strTempProjectWidget = str(tempProjectWidget.getName())
            
            if strTempProjectWidget == name:
                return tempProjectWidget
            
        '''Set the tempWidget in the for loop equal to the return value from here'''
        
    def displayWindow(self):
        
        if self.currentWindowPointer  < self.maxNoOfWindows:
            tempWindow = self.windows[self.currentWindowPointer]
            tempList = []
            '''First set the title to the window'''
            self.window.title(tempWindow.attrib.get('title'))
            
            '''Next construct buttons (If any)'''
            for button in tempWindow.findall('widgets/buttons/button'):
                for tempButton in range(0, len((tempWindow.findall('widgets/buttons/button')))):
                    callback = ProjectWizard.concatCallback(self, button.attrib.get('function'))
                    tempButton = Button(self.window, text=button.attrib.get('text'), name=button.attrib.get('name'), state=button.attrib.get('state'), command=callback)
                    tempButton.grid(row = button.attrib.get('row'), column = button.attrib.get('column'))
                    aButton = ProjectWidget.ProjectWidget(tempButton)
                    aButton.setDestroy(button.attrib.get('destroy'))
                    aButton.setName(button.attrib.get('name'))
                    #tempList.append(tempButton)
                    tempList.append(aButton)
            
            '''Then construct labels (If any)'''
            for label in tempWindow.findall('widgets/labels/label'):
                for tempLabel in range(0, len((tempWindow.findall('widgets/labels/label')))):
                    tempLabel = Label(self.window, text=label.attrib.get('text'), name=label.attrib.get('name'))
                    tempLabel.grid(row = label.attrib.get('row'), column = label.attrib.get('column'))
                    aLabel = ProjectWidget.ProjectWidget(tempLabel)
                    aLabel.setDestroy(label.attrib.get('destroy'))
                    aLabel.setName(label.attrib.get('label'))
                    #tempList.append(tempLabel)
                    tempList.append(aLabel)
            
            '''Then construct text area(s) (If any)'''
            for textArea in tempWindow.findall('widgets/textAreas/textArea'):
                for tempTextArea in range(0, len((tempWindow.findall('widgets/textAreas/textArea')))):
                    tempTextArea = Text(self.window, width = textArea.attrib.get('width'), height = textArea.attrib.get('height'), name=textArea.attrib.get('name'))
                    tempTextArea.grid(row = textArea.attrib.get('row'), column = textArea.attrib.get('column'))
                    aTextArea = ProjectWidget.ProjectWidget(tempTextArea)
                    aTextArea.setDestroy(textArea.attrib.get('destroy'))
                    aTextArea.setPreviousValue(textArea.attrib.get('previousValue'))
                    aTextArea.setName(textArea.attrib.get('name'))
                    #tempList.append(tempLabel)
                    tempList.append(aTextArea)
            
            '''Then construct list box(s) (If any)'''     
            for listBox in tempWindow.findall('widgets/listboxes/listbox'):
                for tempListBox in range(0, len((tempWindow.findall('widgets/listboxes/listbox')))):
                    windownumber= listBox.attrib.get('windowNumber')
                    previousvalue=listBox.attrib.get('previousValue')
                    if listBox.attrib.get('previousValue')==None:
                        if windownumber==None or not int(windownumber) + 1 > len(self.cachedWindows):
                            tempListBox = Listbox(self.window, height=listBox.attrib.get('height'), name=listBox.attrib.get('name'), selectmode=MULTIPLE)
                            tempListBox.grid(row = listBox.attrib.get('row'), column = listBox.attrib.get('column'))
                            aListBox = ProjectWidget.ProjectWidget(tempListBox)
                            aListBox.setDestroy(listBox.attrib.get('destroy'))
                            aListBox.setPreviousValue(previousvalue)
                            aListBox.setName(listBox.attrib.get('name'))
                        else:
                            tempStrName = str(listBox.attrib.get('name'))
                            tempListBoxWidget = self.previousValue(tempStrName, int(windownumber))
                            aListBox = tempListBoxWidget
                       
                    else:
                        tempStrName = str(listBox.attrib.get('name'))
                        tempWindowNumber = int(listBox.attrib.get('windowNumber'))
                        tempListBoxWidget = self.previousValue(tempStrName, tempWindowNumber)
                        aListBox = tempListBoxWidget
                        '''
                        if str(aListBox.getPreviousValue()) != "None":
                            aListBox.setWidget(self.previousValue(aListBox).getWidget())'''
                        
                        #tempList.append(tempLabel)
                        '''tempListBox = aListBox.getWidget()'''
                    tempList.append(aListBox)
                    
            '''Then construct entry(s) (If any)'''
            for entry in tempWindow.findall('widgets/entries/entry'):
                for tempEntry in range(0, len((tempWindow.findall('widgets/entries/entry')))):
                    tempEntry = Entry(self.window, textvariable = entry.attrib.get('name'), name=entry.attrib.get('name'), state=entry.attrib.get('state'))
                    tempEntry.grid(row = entry.attrib.get('row'), column = entry.attrib.get('column'))
                    if not entry.attrib.get('text')==None:
                        tempEntry.delete(0,END)
                        tempEntry.insert(0,entry.attrib.get('text'))
                    aEntry = ProjectWidget.ProjectWidget(tempEntry)
                    aEntry.setDestroy(entry.attrib.get('destroy'))
                    aEntry.setName(entry.attrib.get('name'))
                    #tempList.append(tempLabel)
                    tempList.append(aEntry)
                    
            '''Then construct checkbuttons(s) (If any)'''
            for checkButton in tempWindow.findall('widgets/checkbuttons/checkbutton'):
                for tempCheckButton in range(0, len((tempWindow.findall('widgets/checkbuttons/checkbutton')))):
                    callback = ProjectWizard.concatCallback(self, checkButton.attrib.get('function'))
                    tempCheckButton = Checkbutton(self.window, text=checkButton.attrib.get('text'), command=callback,
                                           variable=checkButton.attrib.get('variable'), name=checkButton.attrib.get('name'))
                    tempCheckButton.grid(row = checkButton.attrib.get('row'), column = checkButton.attrib.get('column'))
                    aCheckButton = ProjectWidget.ProjectWidget(tempCheckButton)
                    aCheckButton.setDestroy(checkButton.attrib.get('destroy'))
                    aCheckButton.setName(checkButton.attrib.get('name'))
                    #tempList.append(tempLabel)
                    tempList.append(aCheckButton)
            
            '''Then construct radiobutton(s) (If any)'''      
            for radioButton in tempWindow.findall('widgets/radiobuttons/radiobutton'):
                for tempRadioButton in range(0,len((tempWindow.findall('widgets/radiobuttons/radiobutton')))):
                    if not radioButton.attrib.get('function')==None:
                        callback = ProjectWizard.concatCallback(self,radioButton.attrib.get('function'))
                    else:
                        callback = None
                    v = IntVar()
                    tempRadioButton = Radiobutton(self.window,
                                                  text=radioButton.attrib.get('text'),
                                                  variable=v,
                                                  value=radioButton.attrib.get('value'),
                                                  name=radioButton.attrib.get('name'),
                                                  command=callback,
                                                  indicatoron=0)
                    tempRadioButton.grid(row = radioButton.attrib.get('row'), column = radioButton.attrib.get('column'))
                    aRadioButton = ProjectWidget.ProjectWidget(tempRadioButton)
                    aRadioButton.setDestroy(radioButton.attrib.get('destroy'))
                    aRadioButton.setName(radioButton.attrib.get('name'))
                    tempList.append(aRadioButton)
              
            self.cachedWindows.insert(self.currentWindowPointer, tempList)
            
            '''if the "corpus review" windows is currently being displayed, then
                iterate through the corpusfolder and add all subfolders to the
                list box in this window '''
            if self.currentWindowPointer == self.corpusReviewWindow:
                fh = FileHandler.FileHandler(None)
                subfolders = fh.getSubfolders(self.corpusPath,False)
                lstCorpusFiles = self.cachedWindows[self.currentWindowPointer][self.iterateCachedWindow('lstCorpusPaths')].getWidget()
                for folder in subfolders:
                    sfolder = folder.split('/')
                    lstCorpusFiles.insert(END,sfolder[len(sfolder)-2]) #subtract 2 because the last element in the list is ''
                lstCorpusFiles.select_set(0,END)
        else:
            self.destroyWindow()
            
    def browseForImportFile(self):
        importFileName = tkFileDialog.askopenfilename()
        if not importFileName:
            return False
        self.mainFrame.getController().updateDocText(importFileName)
        txtExistingDocumentFilename = self.cachedWindows[self.currentWindowPointer][self.iterateCachedWindow('txtExistingDocumentFilename')].getWidget()
        txtExistingDocumentFilename.delete(0,END)
        txtExistingDocumentFilename.insert(0,importFileName)
        txtExistingDocumentFilename.icursor(END) #this doesn't work for some reason
        return True
        
    def browseForCorpusFiles(self):
        corpusFile = tkFileDialog.askopenfilename()
        
        tempWidget = self.cachedWindows[self.currentWindowPointer][self.iterateCachedWindow('fileList')].getWidget()
        
        tempWidget.bind('<<ListboxSelect>>', self.removeFileFromCorpusList)
        strCorpusFile = str(corpusFile)
        #lastBracket = strCorpusFile.rfind("/")
        #strCorpusFile = strCorpusFile[lastBracket + 1:]
        tempWidget.insert(tempWidget.size() + 1, strCorpusFile)
        
    def browseForCorpus(self):
        corpusPath = tkFileDialog.askdirectory()
        if not corpusPath:
            return None
        self.corpusPath = corpusPath
        txtCorpusPath = self.cachedWindows[self.currentWindowPointer][self.iterateCachedWindow('txtCorpusPath')].getWidget()
        txtCorpusPath.delete(0,END)
        txtCorpusPath.insert(0,corpusPath)
    
    def removeFileFromCorpusList(self, *args):
        if self.currentWindowPointer == self.corpusWindow:
            tempWidget = self.cachedWindows[self.currentWindowPointer][self.iterateCachedWindow('removeFromCorpus')].getWidget()
            tempWidget.configure(state=NORMAL)
                
                
    def buttonRemoveFileFromCorpusList(self):
        tempWidget = self.cachedWindows[self.currentWindowPointer][self.iterateCachedWindow('fileList')].getWidget()
        
        currentSelection = tempWidget.curselection()
        tempWidget.delete(currentSelection[0])
        
        removeWidget = self.cachedWindows[self.currentWindowPointer][self.iterateCachedWindow('removeFromCorpus')].getWidget()
        removeWidget.configure(state=DISABLED)
           
    def saveProjectToFile(self):
              
        #prompt for new filename of the project xml
        #projectFile = tkFileDialog.asksaveasfilename()
        
        #initialize file handler
        fh = FileHandler.FileHandler(None)
        
        #construct the project folder name
        userFolder = fh.getCWD()+"/users/"+self.userName
        projectFolder = userFolder+"/"+self.projectTitle
        corpusFolder = fh.getCWD() + "/stylo/corpora/" + self.userName + "-" + self.projectTitle + "/"
        
        #make the project folder if it doesn't exist
        fh.mkdir(userFolder)
        fh.mkdir(projectFolder)
        fh.mkdir(corpusFolder)
        
        #construct project filename
        projectFilename = projectFolder + "/project.xml"
        
        #construct the document filename and
        #copy over the pre-existing document, if the user chose one
        if os.path.isfile(self.existingDocumentFilename):
            documentFilename = projectFolder + "/" + os.path.basename(self.existingDocumentFilename)
            fh.copyFile(self.existingDocumentFilename,documentFilename)
        else:
            documentFilename = projectFolder + "/document.txt"
            fh.writeText(documentFilename,"")
        
        #update wizard with the file path of projectFile
        txtProjectFile = self.cachedWindows[self.currentWindowPointer][self.iterateCachedWindow('txtProjectFile')].getWidget()
        txtProjectFile.configure(state=NORMAL)
        txtProjectFile.insert(0, str(projectFilename))
        
        ###save the project xml file###    
        #make a blank file
        fh.writeText(projectFilename,fh.defaultXML())
        
        #write the project settings to the project file
        fh.loadProject(projectFilename)
        fh.writeProjectSetting("user",self.userName)
        fh.writeProjectSetting("title",self.projectTitle)
        fh.writeProjectSetting("documentFilename",documentFilename)
        fh.writeProjectSetting("corpusPath",corpusFolder)
        fh.saveProject(projectFilename)

        #copy over all the corpus files to the new, local, folder
        lstCorpusPaths = self.cachedWindows[self.currentWindowPointer][self.iterateCachedWindow('lstCorpusPaths')].getWidget()
        for i in range(0,lstCorpusPaths.size()):
            if lstCorpusPaths.selection_includes(i):
                sourcecorpus = self.corpusPath + "/" + lstCorpusPaths.get(i)
                #print("copying " + sourcecorpus + " to " + corpusFolder)
                fh.copyFolder(sourcecorpus,corpusFolder + "/" + lstCorpusPaths.get(i))
        
        self.controller.setFileHandler(fh)
        self.controller.openProject(self.mainFrame,projectFilename)
        
        #TODO: iterate through each fileList widget and write the path name of the corpus to the XML file
        #project filename is 'projectFile'
        
    def concatCallback(self, function):
        return getattr(self, function)
    
    def iterateCachedWindow(self, strWidget):
        for i in range(len(self.cachedWindows[self.currentWindowPointer])):
            tempWidget = self.cachedWindows[self.currentWindowPointer][i].getWidget()
            strTempWidget = str(self.window.nametowidget(tempWidget))
            
            lastDecimal = strTempWidget.rfind(".")
            strTempWidget = strTempWidget[lastDecimal + 1:]
            
            if strTempWidget == strWidget:
                return i